package com.zxcz.service.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zxcz.domain.Devices;
import com.zxcz.domain.IotProduct;
import com.zxcz.domain.PageResult;
import com.zxcz.domain.Resource;
import com.zxcz.domain.Result;
import com.zxcz.domain.User;
import com.zxcz.mapper.UserMapper;
import com.zxcz.redis.RedisManager;
import com.zxcz.service.DevicesService;
import com.zxcz.service.IotProductService;
import com.zxcz.service.ResourceService;
import com.zxcz.service.UserService;
import com.zxcz.tools.Constants;
import com.zxcz.tools.CustomHttpStatus;
import com.zxcz.tools.RedisKeyBuilder;
import com.zxcz.tools.ResultUtil;

@Service
@Transactional
public class UserServiceImpl implements UserService{
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RedissonClient redisson;
	@Autowired
	private ResourceService resourceService;
	@Autowired
	private DevicesService devicesService;
	@Autowired
	private IotProductService iotProductService;
	@Autowired 
	private RedisManager redisManager;
	private static final Log logger = LogFactory.getLog(UserServiceImpl.class);

	/**
	 * 根据账号查询用户
	 */
	@Override
	public User findUserByAccount(String account) {
		return userMapper.findUserByAccount(account);
	}


	/**
	 * 分页
	 */
	@Override
	public PageResult<User> findPage(int pageNum, int pageSize, User user, String productName) {
		// 起始位置
		int pageNumber = (pageNum-1) * pageSize;
		List<User> userList = userMapper.queryUserCondition(pageNumber, pageSize, user, productName);
		Long total = userMapper.getTotal(user, productName);
		
		PageResult<User> pageResult = new PageResult<User>();
		pageResult.setRows(userList);
		pageResult.setTotal(total);
		
		return pageResult;
	}

	/**
	 * 修改密码
	 * @param id 用户id
	 * @param password 需要修改的密码
	 */
	@Override
	public Result<Object> modifyPassword(String password) {
		RLock rLock = redisson.getLock("userLock");
		
		try {
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				// 获取账号
				Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
				String account = authentication.getName();
				// 密码加密
				String passwordEncryption = new BCryptPasswordEncoder().encode(password);
				// 更新数据库
				userMapper.modifyPassword(account,passwordEncryption);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return new ResultUtil().generate(CustomHttpStatus.SERVER_ERROR);
		} finally {
			rLock.unlock();
		}
		
		return new ResultUtil().generate(CustomHttpStatus.SUCCESS);
		
	}

	/**
	 * 根据用户id找到用户
	 * @param id
	 */
	private User findUserById(Integer id) {
		return userMapper.findUserById(id);
	}

	/**
	 * 更新用户
	 * @param user 需要更新的用户
	 */
	@Override
	public Result<Object> updateUser(User user) {
		RLock rLock = redisson.getLock("userLock");
		
		try {
			// 尝试加锁，最多等待10秒，上锁以后5秒自动解锁
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				// 获取用户更改前信息
				User oldUser = this.findUserById(user.getId());
				
				// 更新users表
				user.setUpdatedAt(new Date());
				userMapper.updateUser(user);
				
				// 判断更改了所属产品则同步IOT
				if(user.getIotProductId() != oldUser.getIotProductId()) {
					// IOT注册设备
					devicesService.registerDevice(user);
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			return new ResultUtil().generate(CustomHttpStatus.SUCCESS);
		} finally {
			rLock.unlock();
		}
		
		return new ResultUtil().generate(CustomHttpStatus.SUCCESS);
	}

	/**
	 * 添加用户
	 * @param user 需要添加的用户
	 * @param deviceCount 设备数量
	 */
	@Override
	public Result<Object> insertUser(User user, int deviceCount) {
		RLock rLock = redisson.getLock("userLock");
		
		try {
			// 尝试加锁，最多等待10秒，上锁以后5秒自动解锁
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				
				// 密码加密
				BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
				String password = user.getPassword();
				String pwdMd5 = passwordEncoder.encode(password);
				user.setPassword(pwdMd5);
				user.setCreatedAt(new Date());
				user.setUpdatedAt(new Date());
				// 添加到users表
				userMapper.insertUser(user);
				
				// 添加普通用户角色
				HashMap<String,Object> map = new HashMap<>();
				map.put("userId", user.getId());
				// 一个用户可能有多个角色
				map.put("roleIds", Arrays.asList(Constants.ROLE_USER_ID));
				map.put("createdAt", new Date());
				map.put("updatedAt", new Date());
				// 添加到user_role表
				userMapper.saveUserOrRole(map);
				
				// 添加用户拥有的设备
				devicesService.addDevicesNum(user,deviceCount);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			rLock.unlock();
		}
		
		return ResultUtil.generate(CustomHttpStatus.SUCCESS);
	}

	/**
	 * 根据用户id删除用户
	 * @param id 用户id
	 */
	@Override
	public Result<Object> deleteUserById(int id) {
		RLock rLock = redisson.getLock("userLock");
		
		try {
			// 尝试加锁，最多等待10秒，上锁以后5秒自动解锁
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				// 删除之前先获取用户信息给设备删除
				User user = this.findUserById(id);
				devicesService.deleteDeviceByUser(user);
				// 删除用户资源
				resourceService.deleteResourceByUserId(user.getId());
				
				// 删除用户
				userMapper.deleteUserById(id);
				
				// 删除用户角色
				userMapper.deleteUserOrRole(id);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return new ResultUtil().generate(CustomHttpStatus.SERVER_ERROR);
		} finally {
			rLock.unlock();
		}
		
		return new ResultUtil().generate(CustomHttpStatus.SUCCESS);
	}


	@Override
	public Result<Object> getUserInfo() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String account = authentication.getName();
		User user = userMapper.findUserByAccount(account);
		HashMap<String,Object> map = new HashMap<>();
		map.put("user", user);
		
		return new ResultUtil().generate(CustomHttpStatus.SUCCESS, map);
	}


	@Override
	public Result<Object> queryAllUser() {
		List<User> users = userMapper.queryAllUser();
		HashMap<String, Object> map = new HashMap<>();
		map.put("users", users);
		return new ResultUtil().generate(CustomHttpStatus.SUCCESS, map);
	}
	

}
